/**
* ...
* @author Default
* @version 0.1
*/

package fr.red5.net.so {
	
	import flash.events.Event;
	import flash.events.SyncEvent;
	import flash.net.NetConnection;
	import flash.net.SharedObject;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;	
	import flash.events.IEventDispatcher;
	import flash.events.EventDispatcher;
	
	import fr.red5.events.CallBackEvent;
	import fr.red5.events.SharedObjectEvent;

	public class RemoteSharedObject extends Proxy implements IEventDispatcher  {
		
		private var so:SharedObject;
		private var _data:*;
		private var dispatcher:EventDispatcher;
		private var firstTime:Boolean;
		
		public function RemoteSharedObject(name:String,nc:NetConnection,persistence:Boolean=false){
			firstTime = true;
			dispatcher = new EventDispatcher(this);
			so = SharedObject.getRemote(name,nc.uri,persistence);
			so.addEventListener(SyncEvent.SYNC, soOnSync);
			so.client = this;
			so.connect(nc);
		}
		
		
		flash_proxy override function getProperty(name:*):* {
			var handler:Function = function(... args):void{
				var evt:CallBackEvent = new CallBackEvent(name);
				evt.data = args;
				dispatchEvent(evt);
			}
		    return handler;
		}
		
		
		private function soOnSync(event:SyncEvent):void{
			var results:Object = event.target.data;
			_data = results;
			if (firstTime) {
				firstTime = false;
				for (var name in results){
					var evt:SharedObjectEvent = new SharedObjectEvent(SharedObjectEvent.UPDATE)
					evt.name = name;
					evt.value = results[name];
					dispatchEvent(evt);
				}
			}else{
				var list:Array = event.changeList
				for (var k in list) {
					var id = list[k].name;
					if ((list[k].code == "change") || (list[k].code == "success")){
						var evt:SharedObjectEvent = new SharedObjectEvent(SharedObjectEvent.UPDATE)
						evt.name = id;
						evt.value = results[id];
						evt.oldValue = list[k].oldValue
						dispatchEvent(evt);
					} else if (list[k].code == "delete") {
						var evt:SharedObjectEvent = new SharedObjectEvent(SharedObjectEvent.DELETE)
						evt.name = id;
						evt.value = results[id];
						dispatchEvent(evt);
					}
				}
			}
			dispatchEvent(new SharedObjectEvent(SharedObjectEvent.SYNCHRONIZATION));
		}
		
		public function get data():*
		{
			return _data;
		}
		
		public function clear():void
		{
			so.clear();
		}
		
		public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
			dispatcher.addEventListener(type, listener, useCapture, priority);
		}
	       
		public function dispatchEvent(evt:Event):Boolean{
			return dispatcher.dispatchEvent(evt);
		}
	
		public function hasEventListener(type:String):Boolean{
			return dispatcher.hasEventListener(type);
		}
	
		public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
			dispatcher.removeEventListener(type, listener, useCapture);
		}
	          
	               
		public function willTrigger(type:String):Boolean {
			return dispatcher.willTrigger(type);
		}
		
	}
	
}
